package com.qqt.csr.route.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qqt.csr.common.exception.StatusCode;
import com.qqt.csr.common.idempotent.Idempotent;
import com.qqt.csr.common.idempotent.RequestKeyParam;
import com.qqt.csr.common.utils.CacheKeyUtil;
import com.qqt.csr.common.utils.ServiceAssert;
import com.qqt.csr.route.dto.resp.CsStatusDTO;
import com.qqt.csr.route.entity.CsStatus;
import com.qqt.csr.route.mapper.CsStatusMapper;
import com.qqt.csr.workbench.service.SkillSetMemberService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CsStatusService extends ServiceImpl<CsStatusMapper, CsStatus> {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private SkillSetMemberService skillSetMemberService;

    /**
     * 切换客服状态
     *
     * @param csId
     * @param readyStatus
     * @param workStatus
     */
    @Idempotent(model = "csr-status:m:")
    public void switchStatus(@RequestKeyParam Long csId, String tenantId, Integer readyStatus, Integer workStatus, List<Long> csSkillSetIdList) {
        ServiceAssert.isTrue(StringUtils.isNotBlank(tenantId), StatusCode.Common.ILLEGAL.getCode(), "无效的租户");
        CsStatus csStatus = this.lambdaQuery().select().eq(CsStatus::getCsId, csId).one();
        if (csStatus == null) {
            csStatus = CsStatus.builder()
                    .csId(csId)
                    .readyFlag(readyStatus)
                    .workStatus(workStatus)
                    .build();
            this.save(csStatus);
        } else {
            this.lambdaUpdate().set(CsStatus::getReadyFlag, readyStatus)
                    .set(CsStatus::getWorkStatus, workStatus)
                    .eq(CsStatus::getCsId, csId)
                    .update();
        }

        if (readyStatus.equals(1) && workStatus.equals(0)) {
            //就绪状态而且非忙碌，则加入到缓存中
            addReadyNormalCsId(csId, csSkillSetIdList);
        } else {
            removeNotReadyBusyCsId(csSkillSetIdList, csId);
        }
    }

    /**
     * 查询客服状态
     *
     * @param csId
     * @return
     */
    public CsStatusDTO queryStatus(Long csId) {
        if (csId == null) {
            return CsStatusDTO.builder().csId(csId).workStatus(0).readyFlag(0).build();
        }

        CsStatus csStatus = this.lambdaQuery().select().eq(CsStatus::getCsId, csId).one();
        return CsStatusDTO.builder()
                .workStatus(csStatus != null ? csStatus.getWorkStatus() : 0)
                .readyFlag(csStatus != null ? csStatus.getReadyFlag() : 0)
                .csId(csId)
                .build();
    }

    /**
     * 获取技能组下所有就绪工作正常状态的成员
     *
     * @param skillSetId
     * @return
     */
    public List<Long> getReadyNormalCsIdList(Long skillSetId) {
        if (skillSetId == null) {
            return Lists.newArrayList();
        }
        String redisKey = String.format(CacheKeyUtil.CsrRoute.CS_READY_STATUS_LIST, skillSetId);
        List<Long> csIdList = redissonClient.getSet(redisKey).readAll().stream().map(csId -> (Long) csId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(csIdList)) {
            return csIdList;
        }

        List<Long> skillSetMemberIdList = skillSetMemberService.getCsIdBySkillSetId(skillSetId);
        csIdList = this.lambdaQuery().select(CsStatus::getCsId)
                .in(CsStatus::getCsId, skillSetMemberIdList)
                .eq(CsStatus::getWorkStatus, 0)
                .eq(CsStatus::getReadyFlag, 1)
                .list().stream().map(CsStatus::getCsId).collect(Collectors.toList());
        redissonClient.getSet(redisKey).addAll(csIdList);
        redissonClient.getSet(redisKey).expire(Duration.ofMillis(CacheKeyUtil.EXPIRE_TIME_8H));
        return csIdList;
    }

    /**
     * 将客服加入到就绪工作正常状态的集合中
     *
     * @param csId
     */
    public void addReadyNormalCsId( Long csId, List<Long> skillSetIdList) {
        if (CollectionUtils.isEmpty(skillSetIdList)) {
            return;
        }
        skillSetIdList.forEach(skillSetId -> {
            String redisKey = String.format(CacheKeyUtil.CsrRoute.CS_READY_STATUS_LIST, skillSetId);
            redissonClient.getSet(redisKey).add(csId);
            redissonClient.getSet(redisKey).expire(Duration.ofMillis(CacheKeyUtil.EXPIRE_TIME_8H));
        });
    }

    /**
     * 从缓存中移除非就绪或工作忙碌状态的客服
     *
     * @param csId
     */
    public void removeNotReadyBusyCsId(List<Long> skillSetIdList, Long csId) {
        if (CollectionUtils.isEmpty(skillSetIdList)) {
            return;
        }

        skillSetIdList.forEach(skillSetId -> {
            removeNotReadyBusyCsId(skillSetId, Lists.newArrayList(csId));
        });
    }

    /**
     * 从缓存中移除非就绪或工作忙碌状态的客服
     *
     * @param skillSetId
     * @param csIdList
     */
    public void removeNotReadyBusyCsId(Long skillSetId, List<Long> csIdList) {
        String redisKey = String.format(CacheKeyUtil.CsrRoute.CS_READY_STATUS_LIST, skillSetId);
        csIdList.forEach(csId -> {
            redissonClient.getSet(redisKey).remove(csId);
        });
    }
}
